package util

import (
	"context"
	"encoding/json"
	"fmt"
	"git.internal.yunify.com/huangyingjun/qingbilling-gateway/internal/constants"
	"io/ioutil"
	"os"
	"runtime"
	"strings"
	"sync"

	"google.golang.org/grpc/status"
	"google.golang.org/protobuf/encoding/protojson"
	"google.golang.org/protobuf/proto"

	"git.internal.yunify.com/benchmark/benchmark/pkg/app"
	"git.internal.yunify.com/benchmark/benchmark/pkg/db/pgsql"
	"git.internal.yunify.com/benchmark/benchmark/pkg/global"
	"git.internal.yunify.com/benchmark/benchmark/pkg/grpcx"
)

var one sync.Once

func CooperateCtx() context.Context {
	return Ctx("config.toml", constants.ServiceCooperate)
}

func DefaultCtx() context.Context {
	return Ctx("config.toml", "")
}

func Ctx(configName string, serviceName string) context.Context {
	if c := os.Getenv("PD_CONFIG_PATH"); c != "" {
		configName = c
	}

	_, file, _, _ := runtime.Caller(1)
	arr := strings.Split(file, "test")
	configName = fmt.Sprintf("%sconfigs/%s", arr[0], configName)

	//global配置选项
	options := []global.Option{
		global.WithConfigPath(configName),
		global.WithAppConfig(&app.Config{Service: serviceName, Port: constants.ServiceCooperate}),
		global.WithConfig(grpcx.ConfigInstance()),
	}

	//global依赖组件
	components := []global.Init{
		global.Log(),
		global.Registry(),
	}

	if serviceName != "" {
		components = append(components, global.Pgsql(pgsql.WithDbName(serviceName)))
	}

	one.Do(func() {
		//初始化global
		if err := global.Configure(options...).Use(components...); err != nil {
			panic(err)
		}
	})

	return context.TODO()
}

func StringToProto(v proto.Message, s string) {
	if err := protojson.Unmarshal([]byte(s), v); err != nil {
		fmt.Println("StringToProto:", err)
	}
}

func FileToProto(filePath string, v proto.Message) {
	b, err := ioutil.ReadFile(filePath)
	if err != nil {
		fmt.Println("FileToProto:", err)
	}

	StringToProto(v, string(b))
}
func FileToEntity(filePath string, v interface{}) {
	b, err := ioutil.ReadFile(filePath)
	if err != nil {
		fmt.Println("FileToProto:", err)
	}

	json.Unmarshal(b, v)
}

func CheckResponse(v proto.Message, err error) {
	if err != nil {
		PrintErr(err)
		return
	}

	if v != nil {
		res, _ := protojson.Marshal(v)
		fmt.Printf("RESULT:\n%s\n", res)

	}

}

func PrintProto(v proto.Message) {
	fmt.Println(protojson.MarshalOptions{UseProtoNames: true, Indent: "  "}.Format(v))

}

func PrintErr(err error) {
	if err != nil {
		if s, ok := status.FromError(err); ok {

			res, _ := protojson.Marshal(s.Proto())
			fmt.Printf("ERR:\n%s\n", res)

		} else {
			fmt.Printf("ERR:%v\n", err)

		}
		return
	}
}

//json方式打印结构体
func PrintJson(obj interface{}) {
	tmp, _ := json.MarshalIndent(obj, "", "     ")
	fmt.Println(string(tmp))
}
